<template>
	<view class="local-document-reader">
		<yingbing-html-reader
		ref="reader"
		:page-type="pageType"
		:font-size="fontSize"
		:font-family="fontFamily"
		:line-height="lineHeight + fontSize"
		:color="color"
		back-show
		:background="bgColor"
		:total-chapter="catalog.length"
		preloadable
		@single-click="controlsShow = true"
		@back="handleBack"
		@loadmore="handleLoadmore"
		@change="handleChange"></yingbing-html-reader>
		<view class="position-absolute-cover y-flex" v-show="controlsShow">
			<view class="local-ducment-nav-bar-box" :style="{'background-color': bgColor}">
				<com-nav-bar :title="detail.title" :color="color" status-color="rgba(0,0,0,0)" bg-color="rgba(0,0,0,0)">
					<template #title>
						<com-text lines="2" class="y-flex-1 ml-20 mr-10" weight="bold" line-height="40" size="35" :color="color" :value="detail.title"></com-text>
					</template>
				</com-nav-bar>
			</view>
			<view class="y-flex y-flex-1 position-relative y-align-end y-justify-end">
				<view class="position-absolute-cover" @tap="controlsShow = false"></view>
				<view class="y-flex mb-50 mr-30 position-relative" style="z-index: 1;">
					<view class="local-document-btn-circle mt-40" :style="{'background': bgColor}" @tap="handleRefresh">
						<com-icon name="refresh" size="38" :color="color"></com-icon>
					</view>
					<view class="local-document-btn-circle mt-40" :style="{'background': bgColor}" @tap="handleMarkInsert">
						<com-icon name="edit" size="38" :color="color"></com-icon>
					</view>
					<view class="local-document-btn-circle mt-40" :style="{'background': bgColor}">
						<text class="fs-24" :style="{color: color}">{{progress}}%</text>
					</view>
				</view>
			</view>
			<view class="local-ducment-tabbar-box" :style="{'background-color': bgColor}">
				<view class="y-flex y-row y-align-center page-padding-gap">
					<text class="fs-26" :style="{color: color}" @tap="handlePrev">上一章</text>
					<slider class="y-flex-1" disabled block-size="12" :value="progress" min="0" max="100" :block-color="color" :activeColor="color" :backgroundColor="$utils.hexToRgba(color, 0.5)" />
					<text class="fs-26" :style="{color: color}" @tap="handleNext">下一章</text>
				</view>
				<view class="y-flex y-row y-align-center y-justify-between page-padding-gap pt-30 pb-20">
					<view class="y-flex y-align-center" @tap="handleCatalog">
						<com-icon name="sort" :color="color" size="40"></com-icon>
						<text class="fs-26 y-flex-1 ml-30 mr-30 mt-10" :style="{color: color}">目录</text>
					</view>
					<view class="y-flex y-align-center" @tap="handleMark">
						<com-icon name="tag" :color="color" size="40"></com-icon>
						<text class="fs-26 y-flex-1 ml-30 mr-30 mt-10" :style="{color: color}">书签</text>
					</view>
					<view class="y-flex y-align-center" @tap="settingShow = true">
						<com-icon name="settings_light" :color="color" size="40" weight="bold"></com-icon>
						<text class="fs-26 y-flex-1 ml-30 mr-30 mt-10" :style="{color: color}">设置</text>
					</view>
					<view class="y-flex y-align-center" @tap="$store.dispatch('setting/switchSkinMode')">
						<com-icon :name="skinMode == 'night' ? 'creative_fill' : 'creative'" :color="color" size="40"></com-icon>
						<text class="fs-26 y-flex-1 ml-30 mr-30 mt-10" :style="{color: color}">{{skinMode == 'night' ? '日间' : '夜间'}}</text>
					</view>
				</view>
				<com-safe-bottom></com-safe-bottom>
			</view>
		</view>
		<com-popup :visible.sync="settingShow" direction="bottom">
			<view class="y-flex page-padding-gap pt-50 pb-50" :style="{'background': bgColor}">
				<view class="y-flex y-row pb-60">
					<text class="fs-30 mr-30" :style="{color: color}">字号：</text>
					<view class="y-flex y-row y-align-center">
						<view class="local-document-setting-btn" :style="{'border-color': color}" @tap="handleSetFontSize(-1)">
							<com-icon name="move" :color="color" size="30"></com-icon>
						</view>
						<text class="fs-30 ml-20 mr-20" :style="{color: color}">{{fontSize}}</text>
						<view class="local-document-setting-btn" :style="{'border-color': color}" @tap="handleSetFontSize(1)">
							<com-icon name="add" :color="color" size="30"></com-icon>
						</view>
					</view>
				</view>
				<view class="y-flex y-row pb-60">
					<text class="fs-30 mr-30" :style="{color: color}">行高：</text>
					<view class="y-flex y-row y-align-center y-wrap">
						<view class="local-document-setting-btn mr-5"
						:style="{'border-color': color, 'background': line.value == lineHeight ? color : ''}"
						v-for="(line, i) in lines" :key="i"
						@tap="$store.commit('setting/SET_DOCUMENT_LINE_HEIGHT', line.value)">
							<text class="fs-24" :style="{color: line.value == lineHeight ? bgColor : color}">{{line.label}}</text>
						</view>
					</view>
				</view>
				<view class="y-flex y-row pb-60">
					<text class="fs-30 mr-30" :style="{color: color}">翻页：</text>
					<view class="y-flex y-row y-align-center y-wrap">
						<view class="local-document-setting-btn mr-5"
						:style="{'border-color': color, 'background': type.value == pageType ? color : ''}"
						v-for="(type, i) in pageTypes" :key="i"
						@tap="$store.commit('setting/SET_DOCUMENT_PAGE_TYPE', type.value)">
							<text class="fs-24" :style="{color: type.value == pageType ? bgColor : color}">{{type.label}}</text>
						</view>
					</view>
				</view>
				<view class="y-flex y-row">
					<text class="fs-30 mr-30" :style="{color: color}">背景：</text>
					<view class="y-flex y-row y-align-center y-wrap">
						<view class="local-document-setting-circle mr-5"
						:style="{'border-color': theme.bgColor == bgColor ? color : bgColor, 'background': theme.bgColor}"
						v-for="(theme, i) in themes" :key="i"
						@tap="handleSetTheme(theme)">
						</view>
					</view>
				</view>
			</view>
		</com-popup>
		<com-modal title="记录提示" :content="'本次阅读到 ' + progress + '%\n\n是否保存此次阅读位置'"
		:visible.sync="modalShow"
		:bg-color="skinColor.color_bg_2"
		:title-color="skinColor.color_1"
		:content-color="skinColor.color_2"
		cancel-text="取消保存"
		confirm-text="保存位置"
		@confirm="updatePositon"
		@cancel="handleCancel"></com-modal>
	</view>
</template>

<script>
	import appMixin from '@/common/mixin/app.js'
	import { openDB, closeDB, insert, select, update } from '@/assets/database'
	export default {
		mixins: [appMixin],
		computed: {
			history () {
				return this.$store.getters['setting/GET_HISTORY']
			},
			fontSize () {
				return this.$store.getters['setting/GET_DOCUMENT_FONT_SIZE']
			},
			fontFamily () {
				return this.detail?.fontFamily
			},
			pageType () {
				return this.$store.getters['setting/GET_DOCUMENT_PAGE_TYPE']
			},
			lineHeight () {
				return this.$store.getters['setting/GET_DOCUMENT_LINE_HEIGHT']
			},
			bgColor () {
				return this.skinMode == 'default' ? (this.$store.getters['setting/GET_DOCUMENT_BG_COLOR'] || this.themes[0].bgColor) : this.themes[1].bgColor
			},
			color () {
				return this.skinMode == 'default' ? (this.$store.getters['setting/GET_DOCUMENT_TEXT_COLOR'] || this.themes[0].color) : this.themes[1].color
			},
			network () {
				return this.$store.getters['network/GET']
			}
		},
		data () {
			return {
				modalShow: false,
				settingShow: false,
				controlsShow: false,
				context: {},//正文
				detail: {},//详情
				catalog: [],//章节列表
				record: {},//阅读记录
				current: 0,//当前章节定位
				start: 0,//当前页首字符全文位置
				text: '',//当前页内容
				progress: 0,//当前阅读进度
				currentTitle: '',//当前章节标题
				lines: [{
					label: '最小',
					value: 5
				},{
					label: '较小',
					value: 10
				},{
					label: '适中',
					value: 15
				},{
					label: '较大',
					value: 20
				},{
					label: '最大',
					value: 25
				}],
				pageTypes: [{
					label: '覆盖',
					value: 'cover'
				},{
					label: '仿真',
					value: 'real'
				},{
					label: '滚动',
					value: 'scroll'
				},{
					label: '无动画',
					value: 'none'
				}],
				themes: [{
					bgColor: '#BFAD8A',
					color: '#2E2B23'
				},{
					bgColor: '#393E41',
					color: '#95A3A6'
				},{
					bgColor: '#fff',
					color: '#333'
				},{
					bgColor: '#e3edcb',
					color: '#010103'
				},{
					bgColor: '#fecccb',
					color: '#010103'
				}]
			}
		},
		onReady() {
			this.$utils.setFullscreen(true)
			this.catalog = this.$Route.query.chapters
			this.context = this.$Route.query.context
			this.detail = this.$Route.query.detail
			this.current = this.$Route.query.current || 0
			this.start = this.$Route.query.start || 0
			this.initReader(this.current, this.start)
		},
		onUnload() {
			this.$utils.setFullscreen(false)
		},
		methods: {
			async initReader (current, start) {
				current = parseInt(current)
				start = parseInt(start)
				const chapter = await this.getContent(this.catalog[current], current)
				this.$refs.reader.init({
					chapters: [chapter],
					title: this.detail.title,
					current: current + 1,
					start: start || 0
				})
			},
			async handleLoadmore (index, callback) {
				const chapter = await this.getContent(this.catalog[index - 1], index - 1)
				callback('success', chapter)
			},
			async changeReader (current, start) {
				current = parseInt(current)
				start = parseInt(start)
				const chapter = await this.getContent(this.catalog[current], current)
				this.$refs.reader.change({
					chapters: [chapter],
					current: current + 1,
					start: start || 0
				})
			},
			async getContent (chapter, index) {
				const request = this.context.request
				const params = Object.assign({}, this.detail, chapter)
				const staticData = this.context.staticData ? this.network.staticDataHandle(this.context.staticData, params) : {}
				const dynamicData = this.context.dynamicData || {}
				const newRequest = request ? this.network.requestHandle(request, params) : null
				const response = newRequest ? await this.network.$request(newRequest) : null
				const context = response ? await this.network.$list(dynamicData, response) : null
				return Object.assign({}, staticData, {
					index: index + 1,
					title: chapter.title || '第' + (index + 1) + '章',
					content: context.content.replace(/class="[^"]*"/g, '').replace(/class='[^']*'/g, '').replace(/href="[^"]*"/g, '').replace(/href='[^']*'/g, '').replace(/<img/g, '<img object-fit="scale-down"'),
					isStart: index == 0,
					isEnd: index == this.catalog.length - 1
				})
			},
			handleBack () {
				if ( !this.text ) {
					this.$Router.back()
					return
				}
				if ( this.history == 0 ) {
					this.modalShow = true
				} else if ( this.history == 1 ) this.updatePositon()
				else this.$Router.back()
			},
			handleChange (e) {
				this.current = e.detail.index - 1
				this.start = e.detail.start
				this.currentTitle = e.detail.title || '第' + e.detail.index + '章'
				this.text = e.detail.content.replace(/<[^>]+>/g, '')
				this.progress = e.detail.progress.toFixed(2)
			},
			handlePrev () {
				if ( this.current > 0 ) this.changeReader(this.current - 1)
				else uni.showToast({ title: '已经是第一章了', icon: 'none' })
			},
			handleNext () {
				if ( this.current < this.catalog.length - 1 ) this.changeReader(this.current + 1)
				else uni.showToast({ title: '已经是最后一章了', icon: 'none' })
			},
			handleRefresh () {
				this.$refs.reader && this.$refs.reader.refresh()
			},
			handleCatalog () {
				this.$Router.push({
					path: '/pages/find/novel/chapter',
					query: {
						id: this.detail.uniqueId,
						list: this.catalog,
						title: this.detail.title || '',
						type: 'catalog',
						index: this.current,
					},
					animationType: 'slide-in-right',
					complete: () => {
						uni.$once('find_chapter', e => {
							this.changeReader(e.current)
						})
					}
				})
			},
			handleMark () {
				openDB().then(() => {
					select('mark', 'unique_id = "' + this.detail.uniqueId + '"').then(data=> {
						closeDB()
						const list = data.list
						const index = list.findIndex((item, i) => item.position == this.start && this.current == item.current)
						this.$Router.push({
							path: '/pages/find/novel/chapter',
							query: {
								id: this.detail.uniqueId,
								list: list,
								title: this.detail.title,
								type: 'mark',
								index: index >- 1 ? index : 0
							},
							animationType: 'slide-in-right',
							complete: () => {
								uni.$once('find_chapter', e => {
									this.changeReader(e.current, e.detail.position)
								})
							}
						})
					}).catch(err => {
						closeDB()
						uni.showToast({
							title: err.message,
							icon: 'none'
						})
					})
				})
			},
			handleMarkInsert () {
				openDB().then(() => {
					select('mark', 'unique_id = "' + this.detail.uniqueId + '"').then(data=> {
						const list = data.list
						if ( list.findIndex(item => item.current == this.current && item.position == this.start) == -1 ) {
							const params = {
								uniqueId: this.detail.uniqueId,
								title: this.text.slice(0, 20).replace(/\n/g, ''),
								current: this.current,
								position: this.start
							}
							insert('mark', params).then(()=> {
								closeDB()
								uni.showToast({
									title: '成功插入书签',
									icon: 'none'
								})
							}).catch(err => {
								closeDB()
								uni.showToast({
									title: err.message,
									icon: 'none'
								})
							})
						} else {
							closeDB()
							uni.showToast({
								title: '已经插入过该书签',
								icon: 'none'
							})
						}
					}).catch(err => {
						closeDB()
						uni.showToast({
							title: err.message,
							icon: 'none'
						})
					})
				})
			},
			updatePositon () {
				openDB().then(() => {
					select('record', 'unique_id = "' + this.detail.uniqueId + '"').then(data=> {
						const record = data.list[0] || {}
						if ( record.id ) {
							update('record', {
								url: this.detail.url,
								title: this.detail.title || '',
								cover: this.detail.cover || '',
								current: this.current,
								position: this.start,
								progress: this.progress,
								currentTitle: this.currentTitle,
								is_adult: this.detail.isAdult,
								source_id: this.detail.sourceId
							}, 'id = ' + record.id).then(() => {
								closeDB()
								this.$Router.back()
							}).catch(err => {
								closeDB()
								uni.showToast({
									title: err.message,
									icon: 'none'
								})
								setTimeout(() => {
									this.$Router.back()
								}, 500)
							})
						} else {
							const params = {
								unique_id: this.detail.uniqueId,
								url: this.detail.url,
								title: this.detail.title || '',
								cover: this.detail.cover || '',
								current: this.current,
								position: this.start,
								progress: this.progress,
								current_title: this.currentTitle,
								is_adult: this.detail.isAdult,
								source_id: this.detail.sourceId
							}
							insert('record', params).then(() => {
								closeDB()
								this.$Router.back()
							}).catch(err => {
								closeDB()
								uni.showToast({
									title: err.message,
									icon: 'none'
								})
								setTimeout(() => {
									this.$Router.back()
								}, 500)
							})
						}
					}).catch(err => {
						closeDB()
						uni.showToast({
							title: err.message,
							icon: 'none',
							complete: () => {
								this.$Router.back()
							}
						})
					})
				})
			},
			handleCancel () {
				this.$Router.back()
			},
			handleSetFontSize (value) {
				const fontSize = this.fontSize + value
				if ( fontSize < 15 ) return
				if ( fontSize > 35 ) return
				this.$store.commit('setting/SET_DOCUMENT_FONT_SIZE', fontSize)
			},
			handleSetTheme (theme) {
				this.$store.commit('setting/SET_DOCUMENT_BG_COLOR', theme.bgColor)
				this.$store.commit('setting/SET_DOCUMENT_TEXT_COLOR', theme.color)
			}
		},
		onBackPress(event) {
			if ( event.from == 'backbutton' ) {
				if ( this.modalShow ) {
					this.modalShow = false
					return true
				}
				if ( this.settingShow ) {
					this.settingShow = false
					return true
				}
				if ( this.controlsShow ) {
					this.controlsShow = false
					return true
				}
				if ( this.text ) {
					this.handleBack()
					return true
				}
			}
			return false
		}
	}
</script>

<style>
@keyframes local-document-nav-bar-show {
	from {
		transform: translateY(-100%);
	}
	to {
		transform: translateY(0);
	}
}
@keyframes local-document-tabbar-show {
	from {
		transform: translateY(100%);
	}
	to {
		transform: translateY(0);
	}
}
.local-document-reader {
	height: 100%;
	position: relative;
	overflow: hidden;
}
.local-ducment-nav-bar-box {
	box-shadow: 0 0 20px rgba(0,0,0,.2);
	animation: local-document-nav-bar-show .3s both;
}
.local-ducment-tabbar-box{
	box-shadow: -10px 0 20px rgba(0,0,0,.2);
	animation: local-document-tabbar-show .3s both;
}
.local-document-setting-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100rpx;
	height: 40rpx;
	border-radius: 30rpx;
	border-width: 1px;
	border-style: solid;
}
.local-document-setting-circle {
	width: 80rpx;
	height: 80rpx;
	border-radius: 80rpx;
	border-width: 1px;
	border-style: solid;
}
.local-document-reader-center {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 200rpx;
	height: 200rpx;
}
.local-document-btn-circle {
	width: 100rpx;
	height: 100rpx;
	border-radius: 100rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 0 10px rgba(0,0,0,.2);
}
.local-document-textarea {
	height: 800rpx;
	border-width: 1px;
	border-style: solid;
}
.local-document-textarea-btn {
	height: 100rpx;
	line-height: 100rpx;
}
</style>